package com.yanqu.road.server.gameplayer.module.player;

import com.yanqu.road.entity.config.building.BuildingInfo;
import com.yanqu.road.entity.config.building.BuildingUpgrade;
import com.yanqu.road.entity.config.passroad.PassRoadPointInfo;
import com.yanqu.road.entity.enums.eGamePlayerEventType;
import com.yanqu.road.entity.enums.eLogMoneyType;
import com.yanqu.road.entity.enums.eSkillType;
import com.yanqu.road.entity.log.LogBuildingDispatch;
import com.yanqu.road.entity.log.LogBuildingUpgrade;
import com.yanqu.road.entity.player.UserBuilding;
import com.yanqu.road.entity.player.UserPassRoad;
import com.yanqu.road.entity.player.UserPatrons;
import com.yanqu.road.entity.task.args.BuildingArgs;
import com.yanqu.road.entity.task.args.union.UnionActivityTaskArgs;
import com.yanqu.road.logic.bussiness.player.UserBuildingBussiness;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.logic.pb.BuildingPb;
import com.yanqu.road.pb.building.BuildingProto;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.base.GeneralModule;
import com.yanqu.road.server.gameplayer.module.passRoad.PassRoadModule;
import com.yanqu.road.server.gameplayer.module.patrons.PatronsModule;
import com.yanqu.road.server.manger.DataAnalyticsMgr;
import com.yanqu.road.server.manger.activity.curio.CurioMgr;
import com.yanqu.road.server.manger.config.BuildingMgr;
import com.yanqu.road.server.manger.config.PassRoadMgr;
import com.yanqu.road.server.manger.log.AutoLogMgr;
import com.yanqu.road.server.manger.log.LogMgr;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;

/**
 * 店铺模块
 */
public class BuildingModule extends GeneralModule {

	/**
	 * 店铺集合
	 */
	private Map<Integer, UserBuilding> buildingMap;

	private RandomHelper threadRandom = new RandomHelper();

	public BuildingModule(GamePlayer player) {
		super(player);
	}

	@Override
	public boolean afterLoadData() {
		return false;
	}

	@Override
	public boolean loadData() {
		buildingMap = UserBuildingBussiness.getUserBuildingMap(player.getUserId());
		return true;
	}

	@Override
	public boolean saveData() {
		List<UserBuilding> tempList = new ArrayList<>(buildingMap.values());
		for (UserBuilding userBuilding : tempList) {
			if (userBuilding.isInsertOption()) {
				UserBuildingBussiness.addUserBuilding(userBuilding);
			}else if (userBuilding.isUpdateOption()) {
				UserBuildingBussiness.updateUserBuilding(userBuilding);
			}
		}
		return true;
	}

	@Override
	public void loginSendMsg() {
	    if(null != buildingMap) {
            syncBuilding(new ArrayList<>(buildingMap.values()), true);
        }
	}

	public void syncBuilding(List<UserBuilding> buildingList, boolean login){
	    if(login){
            player.sendPacket(Protocol.U_BUILDING_LIST, BuildingPb.parseBuildingListMsg(buildingList));
        }else {
            player.sendPacket(Protocol.U_BUILDING_SYNC, BuildingPb.parseBuildingListMsg(buildingList));
        }
    }

    private void syncBuilding(UserBuilding userBuilding){
	    if(null == userBuilding){
	        return;
        }
	    List<UserBuilding> buildingList = new ArrayList<>();
	    buildingList.add(userBuilding);
	    syncBuilding(buildingList, false);
    }

    /**
     * 解锁店铺
     */
	public int buildingCreate(int buildingId){
		BuildingInfo buildInfo = BuildingMgr.getBuildingInfo(buildingId);
		if (null == buildInfo) {
			return GameErrorCode.E_BUILDING_NO_FOUND;
		}
		if(buildingMap.containsKey(buildingId)){
			return GameErrorCode.E_BUILDING_ALREADY_CREATE;
		}
		// 通关关卡是否满足
		if(buildInfo.getNeedPassId() > 0) {
			int passId = PassRoadMgr.getFirstPassRoadInfo().getId();
			UserPassRoad userPassRoad = player.getModule(PassRoadModule.class).getUserPassRoad();
			if (null != userPassRoad) {
				PassRoadPointInfo info = PassRoadMgr.getPassRoadPointInfo(userPassRoad.getPassId(),userPassRoad.getPassProgress());
				if(info == null){
					info = PassRoadMgr.getLastPassRoadPointInfo();
				}
				passId = (info.getId() - 1) * 6 + info.getSessionId() + 1;
			}
			if (passId <= buildInfo.getNeedPassId()) {
				return GameErrorCode.E_BUILDING_CREATE_PASS_NO_ENOUGH;
			}
		}
		//按顺序解锁店铺，不能跳级
		int count = buildingMap.size();
		int buildingIndex = BuildingMgr.getBuildingIndex(buildingId);
		if (count + 1 != buildingIndex) {
			return GameErrorCode.E_BUILDING_CREATE_NO_LEAPFROG;
		}

		//消耗解锁材料
		if (!player.getModule(CurrencyModule.class).removeCurrency(buildInfo.getConsume(), eLogMoneyType.Building, eLogMoneyType.BuildingCreate)) {
			return GameErrorCode.E_BAG_SILVER_NO_ENOUGH;
		}
		BigInteger oldEarnSpeed = player.getUserInfo().getEarnSpeed();
		//增加店铺
		addBuilding(buildingId);

		//检测客栈系统解锁
		if(buildingId == GameConfig.INN_BUILD_ID){
			player.getModule(PlayerModule.class).checkSystemOpen();
		}

		//成就、任务
		player.notifyListener(eGamePlayerEventType.RecruitStaffCount.getValue(), 1);
		player.notifyListener(eGamePlayerEventType.UnionRecruitStaffCount.getValue(), new UnionActivityTaskArgs(UnionActivityTaskArgs.TYPE_ADD_VALUE, 1, player.getUserInfo().getUnionUid()));
		player.notifyListener(eGamePlayerEventType.HasBuilding.getValue(), new BuildingArgs(buildingMap));
		player.notifyListener(eGamePlayerEventType.HasLevelBuildingCount.getValue(), new BuildingArgs(buildingMap));
		player.notifyListener(eGamePlayerEventType.BuildingLevel.getValue(), new BuildingArgs(buildingMap));
		player.notifyListener(eGamePlayerEventType.BuildingTotalLevel.getValue(), new BuildingArgs(buildingMap));
		player.notifyListener(eGamePlayerEventType.StaffCount.getValue(), new BuildingArgs(buildingMap));
		player.notifyListener(eGamePlayerEventType.StaffTotalCount.getValue(), new BuildingArgs(buildingMap));
		onBuildingChange();

		//商铺建造
		DataAnalyticsMgr.trackBuildingCreate(player, buildingId, player.getUserInfo().getEarnSpeed(), oldEarnSpeed);
		return 0;
	}

	/**
	 * 店铺升级
	 */
	public int buildingUpgrade(int buildingId) {
		UserBuilding userBuilding = getBuildingById(buildingId);
		if(null == userBuilding){
			return GameErrorCode.E_BUILDING_NO_FOUND;
		}
		// 判断升级条件
		BuildingInfo buildingInfo = BuildingMgr.getBuildingInfo(buildingId);
		int maxLevel = BuildingMgr.getBuildingMaxLevel(player, buildingInfo.getOccupation());
		if(userBuilding.getLevel() >= maxLevel){
			player.notifyListener(eGamePlayerEventType.RechargeBuildingUpgradeNew.getValue(), 0);
			return GameErrorCode.E_BUILDING_MAX_LEVEL;
		}
		BuildingUpgrade nextUpgrade = BuildingMgr.getBuildingUpgrade(buildingId, userBuilding.getLevel() + 1);
		if (null == nextUpgrade) {
			return GameErrorCode.E_BUILDING_MAX_LEVEL;
		}

		BuildingUpgrade buildUpgrade = BuildingMgr.getBuildingUpgrade(buildingId, userBuilding.getLevel());
		if(buildUpgrade.getNeedTitleId() > 0){
			if(player.getTitleId() < buildUpgrade.getNeedTitleId()){
				return GameErrorCode.E_TITLE_LEVEL_NO_ENOUGH;
			}
		}

		//消耗升级材料
		if (!player.getModule(CurrencyModule.class).removeCurrency(buildUpgrade.getConsume(), eLogMoneyType.Building,
				eLogMoneyType.BuildingUpgrade)) {
			player.notifyListener(eGamePlayerEventType.RechargeBuildingUpgradeNew.getValue(), 0);
			return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
		}

		//下一级升级消耗不够
		if(!player.getModule(CurrencyModule.class).currencyIsEnough(nextUpgrade.getConsume())){
			player.notifyListener(eGamePlayerEventType.RechargeBuildingUpgrade.getValue(), 0);
			player.notifyListener(eGamePlayerEventType.RechargeBuildingUpgradeNew.getValue(), 0);
		}

		//店铺等级增加
		int oldLv = userBuilding.getLevel();
		userBuilding.setLevel(userBuilding.getLevel() + 1);

		// 店铺升级
		AutoLogMgr.add(new LogBuildingUpgrade(player.getUserId(), buildingId, oldLv, userBuilding.getLevel(), PropertyHelper.parsePropertyToString(buildUpgrade.getConsume())));
		//成就、任务
		player.notifyListener(eGamePlayerEventType.BuildingLevel.getValue(), new BuildingArgs(buildingMap));
		player.notifyListener(eGamePlayerEventType.HasLevelBuildingCount.getValue(), new BuildingArgs(buildingMap));
		player.notifyListener(eGamePlayerEventType.BuildingTotalLevel.getValue(), new BuildingArgs(buildingMap));
		player.notifyListener(eGamePlayerEventType.BuildingUpgradeTimes.getValue(), 1);
		//检测藏品解锁
		player.getModule(CollectionModule.class).checkCollectionUnlock();
		BigInteger oldEarnSpeed = player.getUserInfo().getEarnSpeed();
		onBuildingChange();
        syncBuilding(userBuilding);

		//商铺升级
		DataAnalyticsMgr.trackBuildingLevelUp(player, buildingId, userBuilding, player.getUserInfo().getEarnSpeed(), oldEarnSpeed);
		return 0;
	}

    /**
     * 招募伙计
     */
	public int addStaff(int buildingId, int addStaffCount){
        UserBuilding userBuilding = getBuildingById(buildingId);
        if(null == userBuilding){
            return GameErrorCode.E_BUILDING_NO_FOUND;
        }
		int count;
		BuildingUpgrade buildingUpgrade = BuildingMgr.getBuildingUpgrade(userBuilding.getBuildingId(), userBuilding.getLevel());
		for (count = 0; count < addStaffCount; count++) {
			int staffCount = userBuilding.getStaffCount();
			if (staffCount >= buildingUpgrade.getMaxStaffCount()) {
				if (0 == count) {
					return GameErrorCode.E_BUILDING_CURRENT_LEVEL_STAFF_MAX;
				} else {
					break;
				}
			}
			BigDecimal removeSilver = BuildingMgr.getAddStaffCost(player, buildingId, staffCount);
			if (null == removeSilver) {
				if (0 == count) {
					return GameErrorCode.E_BUILDING_STAFF_MAX;
				} else {
					break;
				}
			}
			//消耗
			if (!player.getModule(CurrencyModule.class).removeCurrency(new Property(GameConfig.GAME_MONEY_SILVER, removeSilver.toBigInteger()),
					eLogMoneyType.Building, eLogMoneyType.BuildingAddStaff)) {
				if (0 == count) {
					return GameErrorCode.E_BAG_SILVER_NO_ENOUGH;
				} else {
					break;
				}
			}
			//增加员工数量
			userBuilding.setStaffCount(userBuilding.getStaffCount() + 1);
		}

		//成就、任务
		notifyStaffTask(count);
		onBuildingChange();
        syncBuilding(userBuilding);

		//商铺招募伙计
		//DataAnalyticsMgr.trackBuildingRecruit(player, buildingId, userBuilding, count, 0, player.getUserInfo().getEarnSpeed());
		return 0;
    }

	//成就、任务
    public void notifyStaffTask(int count){
		player.notifyListener(eGamePlayerEventType.StaffCount.getValue(), new BuildingArgs(buildingMap));
		player.notifyListener(eGamePlayerEventType.RecruitStaffCount.getValue(), count);
		player.notifyListener(eGamePlayerEventType.UnionRecruitStaffCount.getValue(), new UnionActivityTaskArgs(UnionActivityTaskArgs.TYPE_ADD_VALUE, count, player.getUserInfo().getUnionUid()));
		player.notifyListener(eGamePlayerEventType.StaffTotalCount.getValue(), new BuildingArgs(buildingMap));
	}

    /**
     * 门客派遣
     */
    public int dispatchPatrons(int buildingId, List<Integer> patronsIdList, int operate) {
		UserBuilding userBuilding = getBuildingById(buildingId);
        if (null == userBuilding) {
            return GameErrorCode.E_BUILDING_NO_FOUND;
        }
		//当前总门客
		int currentSize = userBuilding.getPatronsIdList().size();
        PatronsModule patronsModule = player.getModule(PatronsModule.class);
        if (1 == operate) {
			int posLimit = GameConfig.BUILDING_DEFAULT_POS_LIMIT;
			if (player.getTitleId() >= GameConfig.SHOP_SEND_PARTRON_PIT_IDENTITY_NEED) {
				posLimit++;
			}
			if (patronsIdList.size() > posLimit) {
				return GameErrorCode.E_BUILDING_DISPATCH_LIMIT;
			}
			List<Integer> tempList = new ArrayList<>();
            for (int patronsId : patronsIdList) {
                UserPatrons userPatrons = patronsModule.getUserPatrons(patronsId);
                if (null != userPatrons) {
                    tempList.add(patronsId);
                }
            }
            List<Integer> oldPatronsIdList = new ArrayList<>();
            for(int patronsId : userBuilding.getPatronsIdList()){
            	oldPatronsIdList.add(patronsId);
			}
            userBuilding.resetPatrons();
            recallPatrons(patronsIdList);
            for(int patronsId :tempList){
                userBuilding.addPatronsId(patronsId);
            }
            for(int patronsId : tempList){
            	if(!oldPatronsIdList.contains(patronsId)){
					UserPatrons userPatrons = patronsModule.getUserPatrons(patronsId);
					if (null != userPatrons) {
						//派遣日志
						AutoLogMgr.add(new LogBuildingDispatch(player.getUserId(), userBuilding.getBuildingId(), 1, patronsId, userPatrons.getAbility().toString()));
						//埋点
						currentSize++;
					}
				}
			}
            for(int patronsId : oldPatronsIdList){
            	if(!tempList.contains(patronsId)){
					UserPatrons userPatrons = player.getModule(PatronsModule.class).getUserPatrons(patronsId);
					if(userPatrons != null) {
						//撤回日志
						AutoLogMgr.add(new LogBuildingDispatch(player.getUserId(), userBuilding.getBuildingId(), 0, patronsId, userPatrons.getAbility().toString()));
						currentSize--;
					}
				}
			}
        } else {
			//撤回日志
			for(int patronsId : userBuilding.getPatronsIdList()){
				UserPatrons userPatrons = player.getModule(PatronsModule.class).getUserPatrons(patronsId);
				if(userPatrons != null) {
					AutoLogMgr.add(new LogBuildingDispatch(player.getUserId(), userBuilding.getBuildingId(), 0, patronsId, userPatrons.getAbility().toString()));
					currentSize--;
				}
			}
            userBuilding.resetPatrons();
        }
		onBuildingChange();
		//成就、任务
		player.notifyListener(eGamePlayerEventType.BuildingDispatchPatronsCount.getValue(), new BuildingArgs(buildingMap));
		syncBuilding(userBuilding);


        return 0;
    }

	/**
	 * 获取已有的随机建筑
	 */
	public UserBuilding getRandomBuilding(){
		if(buildingMap.size() <= 0){
			return null;
		}
		List<UserBuilding> buildingList = new ArrayList<>(buildingMap.values());
		int index = threadRandom.next(0, buildingList.size());
		return buildingList.get(index);
	}

	/**
	 * 召回门客
	 */
	private void recallPatrons(List<Integer> patronsIdList) {
		List<UserBuilding> syncList = new ArrayList<>();
		for (int patronsId : patronsIdList) {
			if (patronsId > 0) {
				for (UserBuilding userBuilding : buildingMap.values()) {
					if (userBuilding.getPatronsIdList().contains(patronsId)) {
						userBuilding.removePatrons(patronsId);
                        syncList.add(userBuilding);
						//撤回日志
						UserPatrons userPatrons = player.getModule(PatronsModule.class).getUserPatrons(patronsId);
						if(userPatrons != null) {
							AutoLogMgr.add(new LogBuildingDispatch(player.getUserId(), userBuilding.getBuildingId(), 0, patronsId, userPatrons.getAbility().toString()));
						}
					}
				}
			}
		}

		if (syncList.size() > 0) {
			syncBuilding(syncList,false);
		}
	}

	public Map<Integer, UserBuilding> getBuildingMap() {
		return buildingMap;
	}

	public UserBuilding getBuildingById(int buildingId) {
		return buildingMap.get(buildingId);
	}

	public void onBuildingChange() {
		player.getModule(EarnSpeedModule.class).scheduleAddSilver();
	}

	/**
	 * 增加店铺
	 */
	public void addBuilding(int buildingId) {
		if (!buildingMap.containsKey(buildingId)) {
			UserBuilding building = new UserBuilding();
			building.setBuildingId(buildingId);
			building.setLastUpdateTime(System.currentTimeMillis() / 1000);
			building.setLevel(1);
			building.setStaffCount(1);
			building.setUserId(player.getUserId());
			building.setInsertOption();
			buildingMap.put(building.getBuildingId(), building);
			syncBuilding(building);
		}
	}

	/**
	 * 计算建筑员工模块 产金速度
	 */
	public BigInteger calEarnSpeed() {
		BigInteger totalEarnSpeed = BigInteger.ZERO;
		Map<Integer, UserBuilding> copyBuildingMap = new HashMap<>(buildingMap);
		// 计算店铺赚速
		for (UserBuilding building : copyBuildingMap.values()) {
			building.setBuildingEarnSpeed(BuildingMgr.getBuildingEarnSpeed(player, building).toBigInteger());
			totalEarnSpeed = totalEarnSpeed.add(building.getBuildingEarnSpeed());
		}
		player.notifyListener(eGamePlayerEventType.BuildingEarnSpeed.getValue(), new BuildingArgs(copyBuildingMap));
		return totalEarnSpeed;
	}

	public int findPatronsBuildingId(int patronsId) {
		for (UserBuilding building : new ArrayList<>(buildingMap.values())) {
			if (building.getPatronsIdList().contains(patronsId)) {
				return building.getBuildingId();
			}
		}
		return 0;
	}

	public int dispatchPatrons(int buildingId, List<BuildingProto.BuildingDispatchPatronsData> dispatchPatronsDataList) {
		UserBuilding srcBuilding = getBuildingById(buildingId);
		if (null == srcBuilding) {
			return GameErrorCode.E_BUILDING_NO_FOUND;
		}
		PatronsModule patronsModule = player.getModule(PatronsModule.class);

		Set<Integer> srcSet = new HashSet<>();
		Set<Integer> targetSet = new HashSet<>();
		int addPatronsNum = 0;
		Map<Integer, Integer> targetPatronsBuildingMap = new HashMap<>();
		Map<Integer, Integer> targetSrcMap = new HashMap<>();
		//检测参数
		for (BuildingProto.BuildingDispatchPatronsData data : dispatchPatronsDataList) {
			int srcId = data.getSrcPatronsId();
			int targetId = data.getTargetPatronsId();
			if (srcId != 0) {
				UserPatrons userPatrons = patronsModule.getUserPatrons(srcId);
				if (userPatrons == null) {
					return GameErrorCode.E_PATRONS_NO_FOUND;
				}
				if (srcSet.contains(srcId)) {
					return GameErrorCode.E_BUILDING_DISPATCH_LIMIT;
				}
				if (!srcBuilding.getPatronsIdList().contains(srcId)) {
					return GameErrorCode.E_PATRONS_NO_FOUND;
				}
				srcSet.add(srcId);
			}else {
				addPatronsNum++;
			}
			UserPatrons userPatrons = patronsModule.getUserPatrons(targetId);
			if (userPatrons == null) {
				return GameErrorCode.E_PATRONS_NO_FOUND;
			}
			if (targetSet.contains(targetId)) {
				return GameErrorCode.E_BUILDING_DISPATCH_LIMIT;
			}
			targetSet.add(targetId);
			targetPatronsBuildingMap.put(targetId, findPatronsBuildingId(targetId));
			targetSrcMap.put(targetId, srcId);
		}

		//当前总门客
		int currentSize = srcBuilding.getPatronsIdList().size();
		int posLimit = GameConfig.BUILDING_DEFAULT_POS_LIMIT;
		if (player.getTitleId() >= GameConfig.SHOP_SEND_PARTRON_PIT_IDENTITY_NEED) {
			posLimit++;
		}
		if (currentSize + addPatronsNum > posLimit) {
			return GameErrorCode.E_BUILDING_DISPATCH_LIMIT;
		}
		Set<UserBuilding> syncList = new HashSet<>();
		for (Integer id : srcSet) {
			srcBuilding.removePatrons(id);
		}
		syncList.add(srcBuilding);
		for (Integer id : targetSet) {
			srcBuilding.addPatronsId(id);
			UserPatrons userPatrons = patronsModule.getUserPatrons(id);
			AutoLogMgr.add(new LogBuildingDispatch(player.getUserId(), srcBuilding.getBuildingId(), 1, id, userPatrons.getAbility().toString()));
		}
		for (Map.Entry<Integer, Integer> entry : targetPatronsBuildingMap.entrySet()) {
			Integer patronsId = entry.getKey();
			Integer oldBuildingId = entry.getValue();
			UserBuilding building = getBuildingById(oldBuildingId);
			if (building != null) {
				building.removePatrons(patronsId);
				syncList.add(building);
				Integer src = targetSrcMap.get(patronsId);
				if (src != null && !Objects.equals(src, 0)) {
					//不是用0替换
					building.addPatronsId(src);
					//派遣日志
					UserPatrons userPatrons = patronsModule.getUserPatrons(src);
					AutoLogMgr.add(new LogBuildingDispatch(player.getUserId(), building.getBuildingId(), 1, src, userPatrons.getAbility().toString()));
				}
			}
		}
		onBuildingChange();
		//成就、任务
		player.notifyListener(eGamePlayerEventType.BuildingDispatchPatronsCount.getValue(), new BuildingArgs(buildingMap));
		syncBuilding(new ArrayList<>(syncList),false);
		return 0;
	}
}
